#ifndef __MEMORYMANAGER_HPP__
#define __MEMERYMANAGER_HPP__ 1

#include <cstdlib>
#include <map>
#include <list>
#include <vector>

using namespace std;

/*
struct ArenaBlock
{
	size_t startPos;
	size_t endPos;
	ArenaBlock* next;
	void* dataPtr;
};
*/

typedef pair<size_t, size_t> ArenaPos;
typedef list<ArenaPos> ArenaMap;
//typedef pair<size_t, void*> MemoryPair;
typedef ArenaMap::iterator ArenaMapIter;
typedef ArenaMap::const_iterator ArenaMapConstIter;

class CMemoryManager
{
private:
	vector<char> arena;
	ArenaMap arenaMap;
	bool resizable;
	size_t numBlocks;
	size_t blockSize;

public:
	CMemoryManager(size_t arenaSize, bool resizable = false) : resizable(resizable)
	{
		arena.resize(arenaSize);
	}
	~CMemoryManager()
	{

	}

	template<typename T>
	inline T* Alloc(size_t allocSize)
	{
		//size_t startPos = 0, endPos = 0;

		size_t mapStartPos = 0, mapEndPos = 0;

		//size_t mapSize = 0;
		//ArenaBlock* block = new block;
		//block->startPos = 0;
		//block->endPos = 0;
		
		//size_t index = 0;

		ArenaPos pos;

		if(!arenaMap.size())
		{
			pos.first = 0;
			pos.second = allocSize;
			arenaMap.push_back(pos);
			return reinterpret_cast<T*>(&arena[pos.first]);
		}

		auto begin = arenaMap.begin();
		auto end = arenaMap.end();
		for(;;)
		{
			if(begin == end)
			{
				pos.first = mapEndPos+1;
				pos.second = pos.first+allocSize;
				arenaMap.push_back(pos);
				return reinterpret_cast<T*>(&arena[pos.first]);
			}
			mapStartPos = begin->first;
			mapEndPos = begin->second;

			++begin;
			if(begin == end)
				continue;

			if(begin->first - mapEndPos >= allocSize)
			{
				pos.first = mapEndPos+1;
				pos.second = pos.first+allocSize;
				arenaMap.push_back(pos);
				return reinterpret_cast<T*>(&arena[pos.first]);
			}
		}

		//return reinterpret_cast<T*>(NULL);
	}

	template<typename T>
	inline void Free(T* memPtr)
	{
	}
};

#endif